﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;



/// <summary>
/// 按键配置项
/// </summary>
public class KeyItem : MonoBehaviour
{
    private void Update()
    {
        if (!_isEditing) return;
        if (!Input.GetMouseButtonUp(0)) return;
        if (!IsPointerOverEditButton()) FinishEditing();
    }



    public static KeyItem Current { get; private set; }
    public static readonly HashSet<KeyCode> _keyBlacklist = new()
    {
        KeyCode.Mouse0
    };


    [Description("")] public TMP_Text TmpKeyCode;
    [Description("")] public Button BtnEdit;
    [Description("")] public Image Image;

    [Description("")] public DataKeyMap mapping;

    [Description("")] KeyCode _keyCodeCache;
    [Description("")] bool _isEditing;
    [Description("")] EventSystem eventSystem;







    /// <summary>
    /// 初始化按键配置项
    /// </summary>
    /// <param name="mapping">按键映射数据</param>
    public void Init(DataKeyMap mapping)
    {
        BtnEdit = transform.GetComponent<Button>();
        TmpKeyCode = transform.GetChild(0).GetComponent<TMP_Text>();
        Image = transform.GetComponent<Image>();

        this.mapping = mapping ?? throw new ArgumentNullException(nameof(mapping));
        this.UpdateKeyInfo();

        eventSystem = EventSystem.current;
        BtnEdit.onClick.AddListener(OnEditEntered);

        RInputModuleEvent.Register(mapping.keyCode);
        RInputModuleEvent.Get(mapping.keyCode).OnStateChanged += OnImageChanged;
    }

    private void OnImageChanged(KeyEvent @event)
    {
        Image.color = @event.IsPressed ? Color.yellow : Color.white;
    }

    /// <summary>
    /// 更新键值显示信息
    /// </summary>
    private void UpdateKeyInfo()
    {
        if (mapping.isLegacy)
        {
            TmpKeyCode.text = mapping.ToString();
        }
        else
        {
            TmpKeyCode.text = string.IsNullOrEmpty(mapping.newInputSystemPath)
                ? "未绑定"
                : mapping.newInputSystemPath.Split('/').Length > 1
                    ? mapping.newInputSystemPath.Split('/')[1].ToUpper()
                    : mapping.newInputSystemPath.ToUpper();
        }
    }

    /// <summary>
    /// 进入编辑模式
    /// </summary>
    private void OnEditEntered()
    {
        if (Current != null && Current != this)
        {
            Current.FinishEditing();
        }

        BeginEditing();
    }

    /// <summary>
    /// 开始编辑 - 激活按键监听
    /// </summary>
    private void BeginEditing()
    {
        if (_isEditing) return;

        Debug.Log("进入按键监听模式");
        Current = this;
        _isEditing = true;
        TmpKeyCode.text = "";

        StartCoroutine(WaitForKeyInput());
    }

    /// <summary>
    /// 结束编辑 - 关闭按键监听
    /// </summary>
    public void FinishEditing()
    {
        if (!_isEditing) return;  

        Debug.Log("退出按键监听模式");

        _isEditing = false;
        if (Current == this)
        {
            Current = null;
        }
        UpdateKeyInfo();
    }

    /// <summary>
    /// 等待用户输入按键的协程
    /// </summary>
    private IEnumerator WaitForKeyInput()
    {
        while (_isEditing)
        {
            if (Input.anyKeyDown)
            {
                var pressedKey = Enum.GetValues(typeof(KeyCode))
                    .Cast<KeyCode>()
                    .FirstOrDefault(key => Input.GetKeyDown(key) && !_keyBlacklist.Contains(key));

                if (pressedKey != KeyCode.None)
                {
                    Debug.Log($"捕获按键: {pressedKey}");
                    _keyCodeCache = pressedKey;
                    mapping.keyCode = _keyCodeCache;
                    FinishEditing();
                    RInputManager.Instance.rIStorage.Save();
                    yield break;
                }
            }
            yield return null;
        }
    }

    /// <summary>
    /// 检测指针是否在编辑按钮上
    /// </summary>
    private bool IsPointerOverEditButton()
    {
        PointerEventData pointerData = new(eventSystem)
        {
            position = Input.mousePosition
        };

        var results = new List<RaycastResult>();
        eventSystem.RaycastAll(pointerData, results);

        // 直接检测是否包含目标按钮
        return results.Any(result => result.gameObject == BtnEdit.gameObject);
    }
}